package com.xquant.pricing.utils;

import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xquant.pricing.systerm.service.InstrumentService;
import com.xquant.common.engine.xPP.request.CalcEngineParam;
import com.xquant.common.engine.xPP.request.CalcPricingParam;
import com.xquant.common.engine.xPP.request.UnderlyingPricingParam;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * @author B946
 * @date 27/11/2020 10:50
 * @description:
 */
public class EngineParamUtil {


    /**
     * 获取金融工具和spotPrice
     *
     * @param param
     * @return
     */
    public static List<String> getSpotPrices(CalcEngineParam param) {
        JSONObject termsheet = param.getInstrument().getTermsheet();
        JSONArray underlyers = termsheet.getJSONArray("customLegs").getJSONObject(0).getJSONArray("underlyers");
        List<String> list = new ArrayList<>();
        for (int i = 0; i < underlyers.size(); i++) {
            JSONObject underlyer = underlyers.getJSONObject(i);
            list.add(underlyer.getString("instrumentId"));
            list.add(underlyer.getString("spotPrice"));
        }
        return list;
    }

    /**
     * 设置金融工具和spotPrice
     *
     * @param param
     * @param spotPrices
     */
    public static void setSpotPrices(CalcEngineParam param, List<String> spotPrices) {
        JSONObject termsheet = JSON.parseObject(param.getInstrument().getTermsheet().toString());
        JSONArray customLegs = termsheet.getJSONArray("customLegs");
        String notional = termsheet.getString("notional");
        String optionEntitlement = customLegs.getJSONObject(0).getString("optionEntitlement");
        if (StringUtils.isBlank(optionEntitlement) || "0".equals(optionEntitlement)) {
            optionEntitlement = String.valueOf(new BigDecimal(notional).divide(new BigDecimal(spotPrices.get(1)), 6, RoundingMode.HALF_UP));
        }
        for (int i = 0; i < customLegs.size(); i++) {
            customLegs.getJSONObject(i).put("optionEntitlement", optionEntitlement);
            JSONArray underlyers = customLegs.getJSONObject(i).getJSONArray("underlyers");
            for (int j = 0; j < underlyers.size(); j++) {
                JSONObject underlyer = underlyers.getJSONObject(j);
                int index = spotPrices.indexOf(underlyer.getString("instrumentId"));
                if (index != -1) {
                    underlyer.put("spotPrice", spotPrices.get(index + 1));
                }
            }
        }
        param.getInstrument().setTermsheet(termsheet);
        List<CalcPricingParam> calcPricingParams = null;

        if (param.getCalcPricingParam().getLegParams() != null
                && param.getCalcPricingParam().getLegParams().size() != 0) {
            calcPricingParams = param.getCalcPricingParam().getLegParams();
        } else {
            calcPricingParams = ListUtil.toList(param.getCalcPricingParam());
        }
        for (CalcPricingParam calcPricingParam : calcPricingParams) {
            List<UnderlyingPricingParam> underlyingPricingParams = calcPricingParam.getUnderlyingPricingParams();
            underlyingPricingParams.stream().forEach(x -> {
                int index = spotPrices.indexOf(x.getUnderlyingID());
                if (index != -1) {
                    x.setSpotPrice(spotPrices.get(index + 1));
                }
            });
        }
    }

    /**
     * 将FX/EUR/USD转换成系统内可识别的EUR/USD,SPT_XR,X_CNBD
     *
     * @return
     */
    public static String getFxInstructionId(String code) {
        String underCode = code;
        //如果有逗号 则视为正常的格式，不需要转换
        if (com.xquant.pricing.common.utils.StringUtils.isNotNull(code)
                && (!code.contains(",") || code.indexOf(",") == code.length() - 1)) {
            String iCode = code.substring(code.indexOf("/") + 1, code.length());
            //根据内部ICODE和MTYPE去查询标的信息，查询完成后返回逗号分割的内部underCode
            InstrumentService instrumentService = SpringBeanUtils.getBean(InstrumentService.class);
            Map<String, Object> params = new WeakHashMap<>();
            params.put("iCode", iCode);
            List<Map<String, Object>> resultList = instrumentService.getInstruments(params);
            if (resultList.size() > 0) {
                underCode = resultList.get(0).get("code").toString();
            }
        }
        return underCode;
    }
}
